#include <algorithm>
#include "StrFun.h"
#include "Tools.h"

const char * CStrFun::SeparateString(char * pszResult, int iSize, const char * pszStr, const char * pszSpeStr, const int iIdx) const
{
	memset( ( void * )pszResult, 0, iSize );
	if ( IsEmpty( pszStr ) )
	{
		goto __end;
	}
	if ( IsEmpty( pszSpeStr ) )
	{
		goto __end;
	}
	if ( Pos( pszStr, pszSpeStr ) < 0 )
	{
		memcpy((void *)pszResult, (void *)pszStr, iSize);
		goto __end;
	}
	if ( iIdx <= 0 )
	{
		goto __end;
	}
	int iLen = strlen( pszStr );
	int iSpeStrLen = strlen( pszSpeStr );
	int i = 1; 
	int iPos = 0;
	char * szStr = ( char * )pszStr;
	char * szPreStr = NULL;
	while ( szStr[ 0 ] != 0 && i <= iIdx )
	{		
		iPos = Pos( szStr, pszSpeStr );
		if ( -1 == iPos )
		{
			break;
		}		
		szPreStr = szStr;
		szStr += iSpeStrLen + iPos;
		i++;
	}
	if ( ( 0 == iPos ) || ( iIdx > i ) )
	{
		pszResult[ 0 ] = 0;
		goto __end;
	}
	if ( i == iIdx && IsEmpty( szStr ) )
	{
		pszResult[ 0 ] = 0;
		goto __end;
	}	
	if ( iPos > 0 )
	{
		memcpy( ( void * )pszResult, ( void * )szPreStr, iPos);
	}
	else
	{
		int iLength = strlen( szStr );
		if ( 0 == strcmp( pszStr + iLen - iLength, szStr ) )
		{		
			memcpy( ( void * )pszResult, ( void * )szStr, iLength);
		}
	}	
__end:
	return pszResult;
}

const int CStrFun::Pos( const char * pszStr, const char * pszSubStr ) const
{
	int iRetVal = -1;
	char * szRetVal = NULL;
	if ( IsEmpty( pszStr ) )
	{
		goto __end;
	}
	if ( IsEmpty( pszSubStr ) )
	{
		goto __end;
	}
	char *szStr = ( char * )pszStr;
	const char *szTmp = NULL;
	int iLen = strlen( pszSubStr );
	bool bFlg = true;
	szTmp = strstr( pszStr, pszSubStr );
	if ( IsEmpty( szTmp ) )
	{
		goto __end;
	}
	bFlg = true;
	for ( int i = 1; i < iLen; i++ )
		if ( ( szTmp[ i ] != 0 ) && ( szTmp[ i ] != pszSubStr[ i ] ) )
		{
			bFlg = false;
			break;
		}
		if ( bFlg )
		{
			iRetVal = szTmp - pszStr;
		}
__end:
		return iRetVal;
}

const int CStrFun::Pos(const char * pszStr, const int iLen, const char * ptrFind, const int iFindLen)
{
	int iRetVal = -1, i = 0, j = 0;
	if (IsEmpty(pszStr)) goto __end;
	if (IsEmpty(ptrFind)) goto __end;
	if(iLen == 0) goto __end;
	if (iFindLen == 0) goto __end;
	for (; i < iLen; i++)
	{
		if (pszStr[i] != ptrFind[j])
		{
			if (j != 0)j = 0;
		}			
		else if (++j == iFindLen) break;						
	}
	iRetVal = j != 0 ? i - iFindLen : -1;
__end:
	return iRetVal;
}

const int CStrFun::SeparateCount( const char * pszStr, const char * pszSpeStr ) const
{
	int iRetVal = StrCount( pszStr, pszSpeStr );	
	const char * szFlg = pszStr + strlen(pszStr) - strlen(pszSpeStr);
	if ( iRetVal != 0 && strcmp(szFlg, pszSpeStr) != 0 )
	{
		iRetVal++;
	}
__end:
	return iRetVal;
}

const bool CStrFun::IsEmpty( const char * pszStr ) const
{
	return ( !pszStr ) || ( 0 == pszStr[ 0 ] );
}

const char * CStrFun::ParaVal( char * pszResult, int iSize, const char * pszCommandTxt, const char * pszParaName ) const
{
	int iLen = strlen( pszParaName );
	char *szParaName = new char[ iLen + 2 ];
	char *szCommandTxt = ( char * )CaseUpper( pszCommandTxt );
	char *szTmp = ( char * )CaseUpper( pszParaName );
	memset((void *)pszResult, 0, iSize);
	memcpy( ( void * )( szParaName + 1 ), szTmp, iLen + 1 );
	szParaName[ 0 ] = '-';
	try
	{
		int iPos = Pos( szCommandTxt, szParaName );
		if ( iPos < 0 )
		{
			goto __end;
		}
		pszCommandTxt += iPos + strlen( szParaName );
		iPos = Pos(pszCommandTxt, "-" );
		if (iPos > 0)
		{
			pszResult = (char *)Trim(pszResult, iPos, pszCommandTxt);
		}
		else if (!IsEmpty(pszCommandTxt) && iPos != 0)
		{
			pszResult = (char *)Trim(pszResult, strlen(pszCommandTxt), pszCommandTxt);
		}
	}
	catch ( ... )
	{
		goto __end;
	}
__end:
	delete []szParaName;
	szParaName = NULL;
	delete []szTmp;	
	szTmp = NULL;
	delete []szCommandTxt;
	szCommandTxt = nullptr;
	return pszResult;
}

const char * CStrFun::CaseUpper( const char *pszStr ) const
{
	char * szRetVal = NULL;
	if ( IsEmpty( pszStr ) )
	{
		goto __end;
	}
	int iLen = strlen( pszStr );
	szRetVal = new char[ iLen + 1 ];

	for ( int i = 0; i <= iLen; i++ )
	{
		szRetVal[ i ] = toupper( pszStr[ i ] );
	}
	szRetVal[ iLen ] = 0;
__end:
	return szRetVal;
}

const char * CStrFun::Trim( char * pszResult, int iSize, const char * pszStr ) const
{
	//char * szRetVal = NULL;
	char * szStr = ( char * )pszStr;
	memset((void *)pszResult, 0, iSize + 1);
	int iLen = strlen( szStr );
	int iBgnPos = -1, iEndPos = -1;
	for ( int i = 0; i < iLen && ( -1 == iEndPos || -1 == iBgnPos ); i++)
	{
		if ( ( szStr[ iLen - i - 1 ] != 32 ) && ( -1 == iEndPos ) )
		{
			iEndPos = iLen - i;
		}		
		if ( ( szStr[ i ] != 32 ) && ( -1 == iBgnPos ) )
		{
			iBgnPos = i;
		}	
	}
	iLen = iEndPos - iBgnPos;	
	memcpy( ( void * )pszResult, ( void * )( szStr + iBgnPos ), iSize);
__end:
	return pszResult;
}

const char * CStrFun::BeforSeparateString( const char * pszStr, const char * pszSpeStr, const int iIdx ) const
{
	char * szRetVal = NULL;
__end:
	return szRetVal;
}

const int CStrFun::StrCount( const char * pszStr, const char * pszSpeStr ) const
{
	int iRetVal = 0;
	if ( IsEmpty( pszStr ) )
	{
		goto __end;
	}
	if ( IsEmpty( pszSpeStr ) )
	{
		goto __end;
	}
	char *szStr = ( char * )pszStr;
	int iPos = 0;
	int iLen = strlen( pszSpeStr );
	while ( szStr[ 0 ] != 0 )
	{
		iPos = Pos( szStr, pszSpeStr );
		if ( iPos < 0 )
		{
			break;
		}			
		szStr += iPos + iLen;
		iRetVal++;
	}
__end:
	return iRetVal;
}

const bool CStrFun::IsNum(const char * pszStr ) const
{
	bool bRetVal = false;
	char *szNumMod = "+.-0123456789";
	if ( IsEmpty( pszStr ) )
	{
		goto __end;
	}
	int iLen = strlen( pszStr );

	for ( int i = 0; i < iLen; i++ )
	{
		if ( NULL == strchr( szNumMod, pszStr[ i ] ) )
			goto __end;
	}
	bRetVal = true;
__end:
	return bRetVal;
}

const bool CStrFun::GetIniFileSectionInfo( const char * pszIniFile, const char * pszSectionName, void * pvtSectionInfo ) 
{
	bool bRetVal = false;
	if ( !FrameTools().SysFun().PathOrFileExists( pszIniFile ) )
	{
		goto __end;
	}
	if ( IsEmpty( pszSectionName ) )
	{
		goto __end;
	}
	if ( NULL == pvtSectionInfo )
	{
		goto __end;
	}
	vector< string > &vtSectionInfo = *static_cast< vector< string > * >( pvtSectionInfo );
	char szKeyInfo[ 16384 ] = { 0 };
	char *pszKeyInfo = szKeyInfo;
	int isz = GetPrivateProfileIntA( "SETUP", "DataModel", 5, pszIniFile );
	vtSectionInfo.clear();
	if ( GetPrivateProfileStringA( pszSectionName, NULL, NULL, szKeyInfo, sizeof( szKeyInfo ), pszIniFile ) != 0  )
	{
		if ( 0 == szKeyInfo[ 0 ] )
		{
			bRetVal = true;
			goto __end;
		}
		do 
		{
			isz = GetPrivateProfileIntA( pszSectionName, pszKeyInfo, 5, pszIniFile );
			vtSectionInfo.push_back( pszKeyInfo );
			pszKeyInfo += strlen( pszKeyInfo ) + 1;
		} while ( pszKeyInfo[ 0 ] != 0 );
	}

__end: 
	return bRetVal;
}

const bool CStrFun::MemCopy(void * ptrDes, void * ptrSou, int iDesLen, int iSouLen, bool AFullCpyFlg)
{
    bool bRetVal = false;
    int iLen = 0;
    if (ptrDes == nullptr || ptrSou == nullptr)
    {
        goto __end;
    }
    if (iDesLen == 0 || iSouLen == 0)
    {
        goto __end;
    }
    iLen = iDesLen < iSouLen ? iDesLen : iSouLen;
    iLen = AFullCpyFlg || iDesLen > iSouLen ? iLen : iLen - 1;
    memset(ptrDes, 0, iDesLen);
    memcpy(ptrDes, ptrSou, iLen);
__end:
    return bRetVal;
}

const bool CStrFun::CurrToStr(string & strNum, string & strValue, int iDigits, int iCarryNum)
{
	if (strNum.length() == 0) return false;	
	if (!IsNum(strNum.c_str()))  return false;
	string strFloat("");
	int iPrecision = numeric_limits<long double>::digits10;
	iPrecision = iDigits > iPrecision ? iPrecision : iDigits;
	int n = strNum.find(".");
	strValue.assign(strNum, 0, n);
	strFloat.assign(strNum, n, strNum.length());
	int iCount = (strValue.length() / 3) - ((strValue.length() % 3) == 0 ? 1 : 0);
	auto it = strValue.end() - 3;
	for (int i = 1; i <= iCount; i++)
	{
		it = strValue.insert(it, ',');
		if (i < iCount) it -= 3;
	}
	if ((iDigits > 0))
	{
		if ((iDigits + 2) < strFloat.length())
		{
			strFloat[iDigits + 2] = 0;
			strFloat[iDigits] = (strFloat[iDigits + 1] - 48 + iCarryNum) >= 10 ? strFloat[iDigits] + 1 : strFloat[iDigits];
			strFloat[iDigits + 1] = 0;
			if (strFloat[iDigits] == 58)
				for (int i = strlen(strFloat.c_str()) - 1; i > 0; i--)
				{
					if (strFloat[i] == 58)
					{
						strFloat[i] = 48;
						strFloat[i - 1] += 1;
					}
				}
		}
		else
		{
			int iCount = (iDigits + 1) - strFloat.length();
			for (int i = 1; i <= iCount; i++) strFloat.append("0");
		}
		strValue += strFloat;
	}
	return true;
}

const bool CStrFun::CurrToStr(double dNum, string & strValue, int iDigits, int iCarryNum)
{
	bool bRetVal = false;
	char szNum[CHAR_LEN_MAX_NUM] = { 0 };
	gcvt(dNum, numeric_limits<long double>::digits10, szNum);
	string strNum(szNum);
	return CurrToStr(strNum, strValue, iDigits, iCarryNum);
}

const bool CStrFun::CurrToStr(char * pszNum, char * pszValue, int iLen, int iDigits, int iCarryNum)
{
	string strNum(pszNum), strValue("");
	bool bRetVal = CurrToStr(strNum, strValue, iDigits, iCarryNum);
	if (!bRetVal) return false;
	int iDataLen = strValue.length();
	memcpy((void *)strValue.c_str(), (void *)pszValue, (iLen - 1) > iDataLen ? iDataLen : (iLen - 1));
	return bRetVal;
}

const bool CStrFun::CurrToStr(double dNum, char * pszValue, int iLen, int iDigits, int iCarryNum)
{
	bool bRetVal = false;
	char szNum[CHAR_LEN_MAX_NUM] = { 0 };
	gcvt(dNum, numeric_limits<long double>::digits10, szNum);
	return CurrToStr(szNum, pszValue, iLen, iDigits, iCarryNum);
}

char * CStrFun::StrReplace(char * pszSouStr, char * pszDesStr, int iDesSize, const char * pszOld, const char * pszNew)
{
	string strStr = pszSouStr;
	StrReplace(strStr, pszOld, pszNew);
	memset((void *)pszDesStr, 0, iDesSize);
	memcpy((void *)pszDesStr, strStr.c_str(), (iDesSize - 1) > strStr.length() ? strStr.length() : (iDesSize - 1));
	return pszDesStr;
}

string CStrFun::StrReplace(string & strStr, const char * pszOld, const char * pszNew)
{
	int iPos = -1;
	while ((iPos = strStr.find(pszOld)) != -1) strStr.replace(iPos, 1, pszNew);
__end:
	return strStr;
}

const char * CStrFun::KeyVal(char * pszValue, int iSize, const char * pszCommandTxt, const char * pszKeyName, const char * pszSpeStr)  const
{
	memset( ( void * )pszValue, 0, iSize );
	if ( IsEmpty( pszCommandTxt ) )
	{
		goto __end;
	}
	if ( IsEmpty( pszKeyName ) )
	{
		goto __end;
	}
	char *szCommandTx = ( char * )pszCommandTxt;
	int iPos = Pos( szCommandTx, pszKeyName );
	int iLen = strlen( pszKeyName );
	if ( iPos < 0 )
	{
		goto __end;
	}
	szCommandTx += iPos + iLen;
	int iCount = SeparateCount( szCommandTx, pszSpeStr );
	if ( !iCount )
	{
		SeparateString( pszValue, iSize, szCommandTx, "=", 2 );
		goto __end;
	}
	for ( int i = 0; ( 32 == szCommandTx[ 0 ] ) || ( '=' == szCommandTx[ 0 ] ); i++ )
		szCommandTx++;
	SeparateString( pszValue, iSize, szCommandTx, pszSpeStr, 1 );
__end:
	return pszValue;
}

